package com.shenhaofeng.app.adapter;

import android.support.v7.widget.RecyclerView;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * RecyclerView的基础Adapter，扩展了一些数据的载入和移除能力
 * Created by Administrator on 2016/1/4.
 */
public abstract class BaseAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {

    //默认的Item列表;
    private List<T> contentItemGroup = new ArrayList<>();




    /**
     * 这个方法提供item的数量，需要注意的是，这个数量不代表适配器的数据数量，为了添加一些特定的item,
     * 在某些特定时候可能代表一些特定的item的数量，如果需要获取item的数量，请调用{@link #getContentItemCount()}
     *
     * @return
     */
    @Override
    public int getItemCount() {
        return getContentItemCount();
    }


    /**
     * 返回内容的真实大小
     *
     * @return
     */
    protected final int getContentItemCount() {
        return contentItemGroup.size();
    }


    /**
     * 获取适配器中的数据列表
     *
     * @return
     */
    public final List<T> getItems() {
        return contentItemGroup;
    }


    /**
     * 获取指定位置的数据
     *
     * @param position
     * @return
     */
    public T getItem(int position) {
        return getItems().get(position);
    }


    @Override
    public long getItemId(int position) {
        return super.getItemId(position);
    }


    public T findItemById(long id) {
        if (!hasStableIds()) {
            return null;
        }
        for (int i = 0; i < getContentItemCount(); i++) {
            long itemId = getItemId(i);
            if (itemId == id) {
                return getItem(i);
            }
        }
        return null;
    }





    /**
     * 这个方法返回的结果代表的是数据的是否为空
     *
     * @return 现在的版本ContentItem.size()==0的情况下会返回true
     */
    public boolean isEmpty() {
        return contentItemGroup.size() == 0;
    }


    public final int getPosition(T item) {
        return getItems().indexOf(item);
    }


    /**
     * 通过匹配条件来查找Adapter中的指定数据，返回第一个匹配的数据
     *
     * @param item
     * @param equals
     * @return 返回数据在适配器中的位置，如果不存在返回-1
     */
    public final int getPostion(T item, Equals<T> equals) {
        for (int i = 0; i < getContentItemCount(); i++) {
            T itemData = getItem(i);
            if (equals.equals(item, itemData)) {
                return getPosition(itemData);
            }
        }
        return -1;
    }


    /**
     * 添加数据，将这个item添加到最底部,并且通知数据变化
     *
     * @param item
     * @return if item!=null always true.
     */
    public boolean add(T item) {
        if (item == null) {
            return false;
        }
        boolean result = contentItemGroup.add(item);
        notifyItemInserted(getContentItemCount() - 1);
        return result;
    }


    /**
     * 添加一个Item，将这个Item添加到ContentItem的指定位置
     *
     * @param index 这里是ContentGroup中的位置 而不是全局的位置
     * @param item
     */
    public boolean insert(int index, T item) {
        if (item == null) {
            return false;
        }
        getItems().add(index, item);
        notifyItemInserted(index);
        return true;
    }


    /**
     * 添加一组数据,将这组数据添加到指定位置
     *
     * @param index     这里是ContentGroup中的位置 而不是全局的位置
     * @param itemGroup
     */
    public void insertAll(int index, Collection<? extends T> itemGroup) {
        if (itemGroup == null || itemGroup.size() <= 0) {
            return;
        }
        getItems().addAll(index, itemGroup);
        notifyItemRangeInserted(index, itemGroup.size());
    }


    /**
     * 添加一组数据到适配器中
     *
     * @param itemGroup
     */
    public void addAll(Collection<? extends T> itemGroup) {
        if (itemGroup == null || itemGroup.size() <= 0) {
            return;
        }
        int contentSize = getItems().size();
        getItems().addAll(itemGroup);
        notifyItemRangeInserted(contentSize, itemGroup.size());
    }


    /**
     * 开启事务
     *
     * @return
     */
    public AdapterTransaction<T> beginTransaction() {
        return new AdapterTransaction<>(this);
    }


    /**
     * 移除某个Item
     *
     * @param item
     */
    public void remove(T item) {
        if (item == null) {
            return;
        }
        int position = getItems().indexOf(item);
        notifyItemRemoved(position);
        getItems().remove(item);
    }


    public void remove(Filter<T> filter) {
        remove(getItems(), filter);
    }


    public void remove(List<T> items, Filter<T> filter) {
        List<T> removeItem = new ArrayList<>();
        for (int i = 0; i < items.size(); i++) {
            T item = items.get(i);
            if (filter.onAction(item)) {
                removeItem.add(item);

            }
        }
        for (int i = 0; i < removeItem.size(); i++) {
            remove(removeItem.get(i));
        }
    }


    /**
     * 移除指定位置的item,这个方法只适用于单次调用，不要循环调用这个方法，否则删除数据时会错位
     *
     * @param
     */
    public T remove(int position) {
        notifyItemRemoved(position);
        T item = getItems().remove(position);
        return item;
    }


    /**
     * 清除所有数据
     */
    public void clear() {
        int count = getContentItemCount();
        getItems().clear();
        notifyItemRangeRemoved(0, count);
    }


    /**
     * 通知更新指定item
     *
     * @param item
     */
    public void changed(T item) {
        int position = getItems().indexOf(item);
        if (position >= 0) {
            notifyItemChanged(position);
        }
    }


    /**
     * 更新指定位置的item
     *
     * @param position
     */
    public void changed(int position) {
        if (position >= 0 && position < getItemCount()) {
            notifyItemChanged(position);
        }
    }


    /**
     * 替换某个Item的数据
     *
     * @param position
     * @param newItem
     */
    public void replace(int position, T newItem) {
        if (position >= 0 && position < getContentItemCount() && getItems().contains(getItem(position))) {
            getItems().remove(position);
            getItems().add(position, newItem);
            notifyItemChanged(position);
        }
    }


    /**
     * 将数据重新排序
     *
     * @param comparator
     */
    public void sort(Comparator<T> comparator) {
        Collections.sort(contentItemGroup, comparator);
        notifyItemRangeChanged(0, getItemCount());
    }





}
